1. Data Import, Cleaning, and Exploration

a. Install and load the following packages:

b. Import the ACS dataset into your R Markdown or R Notebook.

c. Clean the dataset using the clean_acs_metadata() function provided below.

d. Explore the data by answering the following questions:

  1. What are the dimensions of the dataset (number of rows and columns)?
  2. What are several example column names? Are they understandable?
  3. Which variable should be used as the unique identifier going forward (for filtering and Crosstalk keys)?
clean_acs_metadata <- function(df) {
  
  df_clean <- df %>%
    rename(variable = name) %>%
    
    mutate(
      label_clean = label %>%
        str_remove("^Estimate!!") %>%
        str_replace_all("!!", "_") %>%
        str_replace_all("[^A-Za-z0-9_ ]", "") %>%
        str_replace_all(" +", "_") %>%
        str_to_lower(),
      
      concept_clean = concept %>%
        str_to_lower() %>%
        str_replace_all("[^a-z0-9 ]", "") %>%
        str_replace_all(" +", "_"),
      
      varname = paste0(concept_clean, "_", label_clean),
    ) %>%
  
    select(geoid, state, varname, estimate) %>%
    
    pivot_wider(
      id_cols = c(geoid, state),
      names_from = varname,
      values_from = estimate
    ) %>%
    
    relocate(geoid, state) %>%
    select(-`NA_NA`)
  
  return(df_clean)
}

2. Variable Creation

a. Create new percentage race variables:

b. Create percentage housing tenure variables:

c. Create age bucket variables (using the code provided below):

# Age groups are extremely granular. Bucket them into children (0 - 17), adult (18 - 64), and seniors (65 +)

acs_wide <- acs_wide %>%
  mutate(
    age_children = rowSums(
      select(., matches("sex_by_age_total_(male|female)_(under_5|5_to_9|10_to_14|15_to_17)_years$")),
      na.rm = TRUE
    ),
    age_adults = rowSums(
      select(., matches("sex_by_age_total_(male|female)_(18_and_19|20|21|22_to_24|25_to_29|30_to_34|35_to_39|40_to_44|45_to_49|50_to_54|55_to_59|60_and_61|62_to_64)_years$")),
      na.rm = TRUE
    ),  
    age_seniors = rowSums(
      select(., matches("sex_by_age_total_(male|female)_(65_and_66|67_to_69|70_to_74|75_to_79|80_to_84|85_years_and_older)")),
      na.rm = TRUE      
    )
  )

3. SharedData Object

Before building a Crosstalk dashboard, take a moment to research what a Crosstalk SharedData object is.

a. Explain how a SharedData object differs from a regular data frame.

b. Describe why SharedData is necessary for linking widgets (filters, plots, and tables) to one another in a Crosstalk dashboard.

c. Create your own SharedData object.

4. Crosstalk-Linked Filter

Create a filter_select() that filters the dataset by state.

a. How does the filter_select() know which rows to include/exclude?

b. Why does it only work when the input is a SharedData object?

5. Crosstalk Visualization

Using the same sd SharedData object:

a. Create a Plotly bar chart that displays at least two racial groups.

b. Place the chart next to your state filter using the bscols() layout function.

c. Add a simple HTML summary box that shows a reactive metric (e.g., percent seniors).

See the example below.

Filters


Percent Senior Population: 15%

State Race Composition